home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HPAVC
/
HPAVC CD-ROM.iso
/
PHONG.ZIP
/
SPHERE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1995-10-15
|
5KB
|
195 lines
// Phong Shading Demo. By Keith Harrison (CIS:100431,1675). 15th Oct. 1995
// Shades 20 spheres with differing values of Kd (diffuse)
// and Ks (specular) properties.
// Program uses single equation shading, evaluating only the red component.
// Uses Watcom's graphics library (graph.h)
// Phong's equation for Intensity:
// I = IaKa + Ii[Kd(L.N) + Ks(N.H)ⁿ] / (r + K)
// Developed with Watcom V10.0a from the MS Windows version
// (the Windows version plotted 24bit colour values).
// Based on information in 'Fundamentals of Three-Dimensional Computer
// Graphics' by Alan Watt, ISBN 0 201 15442 0.
#include <conio.h>
#include <graph.h>
#include <math.h>
//Function prototypes.
void setpalette(void);
void plotpixel(short x, short y, short colour);
void ShadeSphere(float Kd, float Ks,
short SpecIndex, short Xcentre, short Ycentre, short radius);
void CalculateLNandNnH( short x, short y, short z, short SpecIndex,
float xn, float yn, float zn,
float *LdotN, float *dist, float *NnH);
//Ambient light intensity (0 to 1)
const float IaKa = 0.2;
//Vector H is the unit normal to the hypothetical surface oriented
//halfway between the light direction vector (L) and the viewing vector (V).
const float Hx = 0.326058, Hy = 0.325058, Hz = 0.888074;
//Intensity of light source.
const short Ilight = 140;
//Light source distance factor.
const float K = 70;
//Light source position.
const float dx = 110, dy = 110, dz = 110;
//Light source normal.
const float Lx = 0.57735, Ly = 0.57735, Lz = 0.57735;
long palette[256];
void setpalette(void)
{
short i;
//The VGA can only handle 64 different shades of red.
for (i=0; i<64; i++)
palette[i] = (long)i;
_remapallpalette( &palette);
};
void plotpixel(short x, short y, short colour)
{
_setcolor(colour);
_setpixel(x, y);
};
void CalculateLNandNnH( short x, short y, short z, short SpecIndex,
float xn, float yn, float zn,
float *LdotN, float *dist, float *NnH)
{
float NH;
*LdotN = xn*Lx + yn*Ly + zn*Lz;
if (LdotN <= 0)
LdotN = 0;
else {
*dist = sqrt((dx - x)*(dx - x) + (dy - y)*(dy - y) + (dz - z)*(dz - z));
NH = Hx*xn + Hy*yn + Hz*zn;
*NnH = exp(SpecIndex*log(NH));
}
};
void ShadeSphere(float Kd, float Ks,
short SpecIndex, short Xcentre, short Ycentre, short radius)
{
short Ir, Igb; // Ir = intensity of Red, Igb = intensity of green/blue.
int x, y, z; // Coordinates of point on sphere surface.
float rsquare, xsquare, ysquare, zsquare, denom, xn, yn, zn, LdotN, NnH,
dist, distfactor, ambientterm, diffuseterm, specularterm;
rsquare = radius * radius;
for (y = -radius; y<radius; y++) {
ysquare = y * y;
for (x = -radius; x<radius; x++) {
xsquare = x * x;
if ( (xsquare + ysquare) <= rsquare) {
z = sqrt(rsquare - xsquare - ysquare);
zsquare = z * z;
denom = sqrt(xsquare + ysquare + zsquare);
// xn, yn, and zn are unit normals from the sphere surface.
xn = x / denom;
yn = y / denom;
zn = z / denom;
CalculateLNandNnH(x, y, z, SpecIndex, xn, yn, zn, &LdotN, &dist, &NnH);
ambientterm = IaKa;
if (LdotN <= 0) {
//Point is not illuminated by light source.
//Use only ambient component.
Ir = 64 * ambientterm;
Igb = 0;
}
else {
distfactor = Ilight / (dist + K);
diffuseterm = distfactor * Kd * LdotN;
specularterm = distfactor * Ks * NnH;
Ir = 64 * (ambientterm + diffuseterm + specularterm);
Igb = 64 * specularterm;
};
plotpixel(Xcentre + x, Ycentre + y, Ir);
}
}
}
};
int main(int argc, char *argv[])
{
short SpecIndex, i, j, Xpos, Ypos;
float Kd, Ks;
int videomode;
if (argc != 2) {
printf("\nPhong Shaded Spheres.\n");
printf("By Keith Harrison.\n\n");
printf("Usage: sphere <video_mode>\n");
printf("Video modes: 320 = 320 x 200 x 256 colour (VGA)\n");
printf(" 640 = 640 x 480 x 256 colour (SVGA)\n");
printf(" 800 = 800 x 600 x 256 colour (SVGA)\n");
printf(" 1024 = 1024 x 768 x 256 colour (SVGA)\n\n");
return 1;
};
videomode = atoi(argv[1]);
switch (videomode) {
case 320: _setvideomode( _MRES256COLOR ); break;
case 640: _setvideomode( _VRES256COLOR ); break;
case 800: _setvideomode( _SVRES256COLOR ); break;
case 1024: _setvideomode( _XRES256COLOR ); break;
default:
printf("\nIncorrect command line option.\n");
printf("Defaulting to 640 x 480 x 256 colours\n");
printf("Type 'sphere' to see options\n");
printf("Press any key to continue.\n");
getch();
_setvideomode( _VRES256COLOR ); break;
};
setpalette();
SpecIndex = 9;
Ypos = 50;
for (i=0; i<4; i++) {
Xpos = 50;
Kd = 0;
Ks = 1;
for(j=0; j<5; j++) {
ShadeSphere(Kd, Ks, SpecIndex, Xpos, Ypos, 50);
Kd += 0.25;
Ks -= 0.25;
Xpos += 110;
};
Ypos += 110;
SpecIndex = SpecIndex * 2;
};
getch();
_setvideomode( _DEFAULTMODE );
return 0;
}